package org.springblade.tms.module.supercargoinfo.importer;

import cn.hutool.core.collection.ListUtil;
import com.google.common.base.Strings;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springblade.common.utils.StreamUtils;
import org.springblade.core.excel.support.ExcelImporter;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.tms.global.constant.DateConstant;
import org.springblade.tms.module.supercargoinfo.base.EscortManagementService;
import org.springblade.tms.module.supercargoinfo.entity.TMSupercargoInfo;
import org.springblade.tms.module.supercargoinfo.vo.TMSupercargoInfoExcelVo;
import org.springblade.tms.module.userinfo.entity.TMUserInfo;
import org.springframework.data.redis.core.RedisTemplate;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.module.supercargoinfo.Importer
 * @className: EscortManagementImporter
 * @author: yr
 * @description: 押运员数据导入类
 * @date: 2022/4/22 16:13
 */
@RequiredArgsConstructor
public class EscortManagementImporter implements ExcelImporter<TMSupercargoInfoExcelVo> {
	//服务
	private final EscortManagementService service;
	//线程
	private final ThreadPoolExecutor executor;
	//验证器
	private final Validator validator;
	//当前用户
	private final TMUserInfo TMuserInfo;
	//reidsKey
	private final String ImportNo;

	private final RedisTemplate redisTemplate;


	@Override
	@SneakyThrows
	public void save(List<TMSupercargoInfoExcelVo> data) {
		BladeUser user = AuthUtil.getUser();
		//验证器验证
		List<TMSupercargoInfoExcelVo> failure = new ArrayList<>();
		List<Set<ConstraintViolation<TMSupercargoInfoExcelVo>>> setList = data.stream()
			.map(driverExcel -> validator.validate(driverExcel)).filter(validate -> !validate.isEmpty()).collect(Collectors.toList());
		setList.forEach(constraintViolations -> constraintViolations.
			forEach(driverExcelVoConstraintViolation -> {
				TMSupercargoInfoExcelVo driverExcelVo = driverExcelVoConstraintViolation.getRootBean();
				failure.add(driverExcelVo);
			}));
		//失败条数放入redis
		List<TMSupercargoInfoExcelVo> failure1 = failure.stream().distinct().collect(Collectors.toList());
		data.removeAll(failure1);
		AtomicLong count = new AtomicLong(failure1.size());
		Map<String, List<TMSupercargoInfoExcelVo>> dataMap = data.stream().collect(Collectors.groupingBy(TMSupercargoInfoExcelVo::getPhone));
		//每500条数据开一个线程
		List<TMSupercargoInfo> tmSupercargoInfoList = BeanUtil.copy(data, TMSupercargoInfo.class);
		tmSupercargoInfoList.forEach(tmSupercargoInfo -> {
			//时间类型转换
			String cardValidEnd = dataMap.get(tmSupercargoInfo.getPhone()).get(0).getIdCardValidEnd();
			if (cardValidEnd.equals("长期")) {
				tmSupercargoInfo.setIdCardValidEnd(LocalDateTime.MAX);
				Instant instant4 = DateUtil.parse(DateConstant.LONG_TIME, DateConstant.NORMAL_FORMAT).toInstant();
				tmSupercargoInfo.setIdCardValidEnd(LocalDateTime.ofInstant(instant4, ZoneId.systemDefault()));
			} else {
				Instant instant2 = DateUtil.parse(cardValidEnd, DateConstant.NORMAL_FORMAT).toInstant();
				tmSupercargoInfo.setIdCardValidEnd(LocalDateTime.ofInstant(instant2, ZoneId.systemDefault()));
			}
			String validityPeriod = dataMap.get(tmSupercargoInfo.getPhone()).get(0).getValidityPeriod();
			if (!Strings.isNullOrEmpty(validityPeriod)) {
				if (validityPeriod.equals("长期")) {
					tmSupercargoInfo.setValidityPeriod(LocalDateTime.MAX);
					Instant instant4 = DateUtil.parse(DateConstant.LONG_TIME, DateConstant.NORMAL_FORMAT).toInstant();
					tmSupercargoInfo.setValidityPeriod(LocalDateTime.ofInstant(instant4, ZoneId.systemDefault()));
				} else {
					Instant instant2 = DateUtil.parse(validityPeriod, DateConstant.NORMAL_FORMAT).toInstant();
					tmSupercargoInfo.setValidityPeriod(LocalDateTime.ofInstant(instant2, ZoneId.systemDefault()));
				}
			}
			Instant instant1 = dataMap.get(tmSupercargoInfo.getPhone()).get(0).getIdCardValidStart().toInstant();
			LocalDateTime idCardValidStart = LocalDateTime.ofInstant(instant1, ZoneId.systemDefault());
			tmSupercargoInfo.setIdCardValidStart(idCardValidStart);
		});
		List<List<TMSupercargoInfo>> split = ListUtil.split(tmSupercargoInfoList, 500);
		List<CompletableFuture<Void>> taskList = new ArrayList<>();
		split.forEach(list -> taskList.add(
			CompletableFuture.supplyAsync(() -> {
				list.forEach(supercargoInfo -> {
					try {
						supercargoInfo.setTenantId(user.getTenantId());
						supercargoInfo.setCreateUser(user.getUserId());
						supercargoInfo.setCreateDept(Long.valueOf(user.getDeptId()));
						R save = service.save(supercargoInfo, TMuserInfo);
						if (!save.isSuccess()) {
							count.getAndIncrement();
						}
					} catch (Throwable e) {
						count.getAndIncrement();
					}

				});
				return null;
			}, executor)
		));
		taskList.forEach(StreamUtils.ofConsumer(voidCompletableFuture -> voidCompletableFuture.get()));
		redisTemplate.opsForValue().set(ImportNo, count.longValue());
	}
}
